/*!
 * @file inifile.cpp
 * @brief Ciało inifile.hh
 */

#include "engine/basic/inifile.hh"
using namespace std;

/*--------------------------------------------------------------------------*/

inifile::inifile(string path) :
	isFileLoaded(false), path(path) {

	this->load();
}

/*--------------------------------------------------------------------------*/

int inifile::getInteger(std::string section, std::string name, int defaultVal) const {

	if(!this->isFileLoaded) return defaultVal;

	inifileItem *item = this->getItem(section, name);

	if (item) {
		return item->getInt();
	} else {
		return defaultVal;
	}
}

/*--------------------------------------------------------------------------*/

float inifile::getFloat(std::string section, std::string name, float defaultVal) const {

	if(!this->isFileLoaded) return defaultVal;

	inifileItem *item = this->getItem(section, name);

	if (item) {
		return item->getFloat();
	} else {
		return defaultVal;
	}
}

/*--------------------------------------------------------------------------*/

string inifile::getString(std::string section, std::string name,
		string defaultVal) const {

	if(!this->isFileLoaded) return defaultVal;

	inifileItem *item = this->getItem(section, name);

	if (item) {
		return item->getString();
	} else {
		return defaultVal;
	}
}

/*--------------------------------------------------------------------------*/

inifileItem *inifile::getItem(std::string section, std::string name) const {

	inifileSection *sec = this->getSection(section);

	if (sec == NULL) {
		stringstream ss;
		ss << "Nie znaleziono sekcji [" << section << "] w " << this->path;
		log::warning(ss.str());

		return NULL;
	}

	inifileItem *item = sec->getItem(name);

	if (item == NULL) {
		stringstream ss;
		ss << "Nie znaleziono zmiennej " << name << " w sekcji [" << section
				<< "] w pliku " << this->path;
		log::warning(ss.str());

		return NULL;
	}

	return item;
}

/*--------------------------------------------------------------------------*/

inifileSection *inifile::getSection(std::string section) const {

	for (list<inifileSection *>::const_iterator I =
			this->inisections_stack.begin(); I
			!= this->inisections_stack.end(); I++) {

		if ((*I)->getName() == section) {
			return (*I);
		}
	}

	return NULL;
}

/*--------------------------------------------------------------------------*/

void inifile::load() {

	ifstream file(this->path.c_str());

	if (!file.is_open()){
		stringstream ss;
		ss << "Nie udało się otworzyć pliku " << this->path;

		log::error(ss.str());

		return;
	}

	const int lineLength = 512;
	char tmpt[lineLength];

	inifileSection *active_section = NULL;

	while (file.getline(tmpt, lineLength)) {

		if (tmpt[0] == '#')
			continue;

		if (tmpt[0] == '\n')
			continue;

		if (tmpt[0] == '[') {
			int i = 1;
			string section;
			while (tmpt[i] != ']') {
				section += tmpt[i];
				++i;
			}
			if (active_section != NULL)
				this->inisections_stack.push_back(active_section);

			active_section = new inifileSection(section);
		} else {
			int i = 0;
			bool isName = true;
			string name, value;
			while (tmpt[i] != '\0') {
				if (isName) {
					if (tmpt[i] != '=')
						name += tmpt[i];
					else
						isName = false;
				} else {
					value += tmpt[i];
				}
				++i;
			}

			if(active_section == NULL)
				active_section = new inifileSection("");

			active_section->addItem(name, value);
		}
	}
	file.close();

	if(active_section != NULL)
		this->inisections_stack.push_back(active_section);

	this->isFileLoaded = true;
}

/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

inifileSection::inifileSection(std::string name) :
	name(name) {

}

/*--------------------------------------------------------------------------*/

void inifileSection::addItem(std::string name, std::string value) {

	this->sectionitem_stack.push_back(new inifileItem(name, value)     );

}

/*--------------------------------------------------------------------------*/

string inifileSection::getName() const {
	return this->name;
}

/*--------------------------------------------------------------------------*/

inifileItem *inifileSection::getItem(std::string name) const {

	for (list<inifileItem *>::const_iterator I = this->sectionitem_stack.begin(); I
			!= this->sectionitem_stack.end(); I++) {

		if ((*I)->getName() == name) {
			return (*I);
		}
	}

	return NULL;
}

/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

inifileItem::inifileItem(std::string name, std::string value) :
	name(name), value(value) {

}

/*--------------------------------------------------------------------------*/

int inifileItem::getInt() const {
	int tmp;
	stringstream ss;
	ss << this->value;
	ss >> tmp;

	return tmp;
}

/*--------------------------------------------------------------------------*/

float inifileItem::getFloat() const {
	float tmp;
	stringstream ss;
	ss << this->value;
	ss >> tmp;

	return tmp;
}

/*--------------------------------------------------------------------------*/

string inifileItem::getString() const {
	return this->value;
}

/*--------------------------------------------------------------------------*/

string inifileItem::getName() const {
	return this->name;
}

/*--------------------------------------------------------------------------*/
